<template>
  <div class="material dialog">
    <transition name="fade">
      <div class="dialog-mask" v-show="visible"></div>
    </transition>

    <div class="dialog-wrap" :class="{'wrap--hide': !isWrapShow}">
      <div class="dialog-center-fixed">
        <transition name="drop">
          <div class="dialog-main" v-show="visible">
            <div class="dialog-content">
              <div class="header">
                <h3 class="title">
                  <span>我的素材库</span>
                </h3>
                <a class="close" @click="onCancel">
                  <i class="close-icon">x</i>
                </a>
              </div>
              <div class="body">
                <div class="body-inner" :class="{'uploading-info--show': isShowUploadingInfo}">
                  <uploading-info
                    :upload-list="uploadList"
                    :upload-file="uploadFile"
                    @on-see="isShowUploadingList = true"
                  />

                  <div class="tabs">
                    <ul>
                      <li
                        v-for="(tab, index) in materialCategory"
                       :key="index"
                        class="tab"
                       :class="{'active': currentMaterialType === tab.key }"
                      >
                        <span @click="onTypeChanged(tab.key)">{{ tab.value }}</span>
                      </li>
                    </ul>

                    <uploader
                      ref="uploader"
                     :acceptTypes="acceptTypes"
                     :acceptSizes="acceptSizes"
                     :currType="currentMaterialType"
                      @update-queue="handleUploadListChanged"
                      @update-file="handleUploadFileChanged"
                      @on-success="handleUploadSuccess"
                      @on-rejected="onRejected"
                    />
                  </div>
                  <div class="pane">
                    <template v-if="materialList.length">
                      <ul class="material-list" :class="{'picture-card': isShowImageCard}">
                        <li
                          v-for="item in materialList"
                         :key="item.materialId"
                          class="material-item"
                         :class="{
                           'disabled': disableSelect(item),
                           'selected': isSelected(item)
                         }"
                        >
                          <div class="item-wrapper" @click="() => onSelected(item)">
                            <div class="item-choice">
                              <selector
                                :value="isSelected(item)"
                                :mode="mode === 0 ? 'radio' : 'checkbox'"
                                :disabled="disableSelect(item)"
                              />
                            </div>
                            <div class="item">
                              <div class="icon">
                                <i class="icon-mask"></i>
                                <img :src="item.snapshotCover" alt="">
                              </div>
                              <div class="file">
                                <div class="name">{{ item.materialFullName }}</div>
                                <div class="info">
                                  <div class="size" v-if="item.materialStatus !== 'error'">
                                    <span>{{ formatFileSize(item.materialSize) }}</span>
                                  </div>
                                  <div class="time-or-status">
                                    <template v-if="item.materialStatus === 'usable'">
                                      <div class="time">
                                        <span>{{ formatTime(item.gmtCreate) }}</span>
                                      </div>
                                    </template>
                                    <template v-else>
                                      <div class="status">
                                        <span v-if="item.materialStatus === 'transcoding'" class="transcoding">转码中，关闭窗口不影响转码</span>
                                        <span v-if="item.materialStatus === 'failed'" class="error">
                                          <span class="s1">转码失败</span>
                                        </span>
                                      </div>
                                    </template>
                                  </div>
                                </div>
                              </div>
                            </div>
                          </div>
                        </li>
                      </ul>
                    </template>
                    <template v-else>
                      <div class="is-empty">
                        <img src="./assets/img_empty.png" alt="">
                        <p>暂无内容，请先上传素材</p>
                      </div>
                    </template>
                  </div>
                </div>
              </div>

              <pager
               :pageIndex="pageIndex"
               :total="total"
                @on-change="onPageChanged"
              />
              <div class="footer">
                <div class="tips">
                  <template v-if="limit">
                    <span>最多可插入{{ limit }}个文件</span>
                  </template>
                </div>
                <div class="btns">
                  <span class="btn cancel" @click="onCancel">取消</span>
                  <span class="btn insert" :class="{'disabled': disableInsert }" @click="onInsert">插入
                    <template v-if="mode && !disableInsert">
                      <span>(</span>
                      <span class="count">{{ selected.length }}</span>
                      <span>)</span>
                    </template>
                  </span>
                </div>
              </div>
            </div>
          </div>
        </transition>
      </div>
    </div>

    <uploading-list
      v-model:value="isShowUploadingList"
     :upload-list="uploadList"
      @on-re-upload="handleReUploadByKey"
      @on-remove="handleUploadFileRemove"
    />
  </div>
</template>

<script>
import Uploader from './uploader';
import Selector from './selector';
import Pager from './pager';
import UploadingInfo from './uploading-info/index';
import UploadingList from './uploading-list/index';
import {
  getMaterialTypeTabs,
  getFileAcceptType,
  formatFileSize,
  formatTime
} from './core/helper';

/**
 * 注意：props不要传字面量
 *
 * category => key: ['all', 'document', 'audio', 'video', 'img', 'other']
 * subCategory: 子分类
 * mode: 0.single 1.multiple
 * listType: 0.text 1.picture-card
 * selectedIds: 已选择的素材(id)列表
 * limit: 限制可勾选的素材数量
 * limitSize: 限制文件上传大小 Number | Object: { document: Infinity, audio: Infinity, video: Infinity, img: Infinity } 单位：byte
 * isForciblySelect: 是否允许转码中选择素材，默认开启
 *
 * materialItem: {
 *    materialId: "5586075009669160960",
 *    materialFullName: "素材名称.mp4",
 *    materialNameSuffix: "mp4",
 *    materialSize: 49250053,
 *    materialStatus: "usable",
 *    * materialType: "video",// unknown | img | [pdf|ppt|doc|xls] | audio | video |
 *    materialUrl: "https://srt-read-dev.3ren.cn/basebusiness/material/20210714/1626249772477zHHhJETTMB001.mp4",
 *    * transferFileUrl: "https://srt-read-dev.3ren.cn/basebusiness/material/20210714/transcode/b8e4ffdd-089c-40a1-b2dd-139134894c28/1bf61b4b-5dde-43e4-9708-f1521d33e326.m3u8",
 *    * previewUrl: "https://preview.imm.aliyun.com/index.html?url=https://srt-read-dev.3ren.cn/basebusiness/material/20210715/16263133846115P41Q6VxyG017&cookie=0"
 *    snapshotCover: "https://srt-read-dev.3ren.cn/basebusiness/material/20210714/1626249772477zHHhJETTMB001.jpg?x-oss-process=image/resize,m_fill,h_400,w_400,limit_0",
 *    gmtCreate: 1626852827327
 * }
 */
export default {
  components: {
    Uploader,
    Selector,
    Pager,
    UploadingInfo,
    UploadingList
  },

  props: {
    value: Boolean,
    category: {
      type: Array,
      default: () => ['all', 'document', 'audio', 'video', 'img', 'other']
    },
    subCategory: {
      type: Array,
      default: () => []
    },
    mode: {
      type: Number,
      default: 1
    },
    listType: {
      type: Number,
      default: 0
    },
    selectedIds: {
      type: Array,
      default: () => []
    },
    isForciblySelect: {
      type: Boolean,
      default: true
    },
    limit: Number,
    limitSize: [Number, Object]
  },
  data() {
    return {
      visible: this.value,
      isWrapShow: this.value,

      currentMaterialType: '',
      pageIndex: 1,
      pageSize: 10,
      total: 0,
      materialList: [],
      selected: [],
      cached: [],

      uploadList: [],
      uploadFile: {},
      isShowUploadingList: false
    }
  },
  computed: {
    materialCategory() {
      return getMaterialTypeTabs(this.category);
    },
    acceptTypes() {
      return getFileAcceptType(this.subCategory);
    },
    acceptSizes() {
      const defaultAcceptSizes = {
        document: Infinity,
        audio: Infinity,
        video: Infinity,
        img: Infinity
      };

      if (Object.prototype.toString.call(this.limitSize) === '[object Object]') {
        return Object.assign(defaultAcceptSizes, this.limitSize);
      }

      if (Object.prototype.toString.call(this.limitSize) === '[object Number]') {
        Object.keys(defaultAcceptSizes).forEach(key => {
          defaultAcceptSizes[key] = this.limitSize
        });
      }

      return defaultAcceptSizes;
    },

    isShowImageCard() {
      return this.listType && this.currentMaterialType === 'img'
    },
    isShowUploadingInfo() {
      return !!this.uploadList.length;
    },

    isTranscoding() {
      return this.materialList.some(item => item.materialStatus === 'transcoding');
    },

    isFilled() {
      return this.selected.length >= this.limit;
    },

    isSelected() {
      return (item) => this.selected.includes(item.materialId);
    },
    // 禁用选中
    disableSelect() {
      return (item) => (item.materialStatus === 'failed' || !this.isForciblySelect && item.materialStatus !== 'usable') || 
      (this.isFilled && !this.selected.includes(item.materialId)) || 
      (this.currentMaterialType && this.acceptSizes[this.currentMaterialType] < item.materialSize)
    },
    // 禁用插入
    disableInsert() {
      return this.selected.length === 0;
    },

    // 动态获取素材库可上传类型
    isSearchTypeChanged() {
      let { category, subCategory } = this;

      return {
        category,
        subCategory
      }
    }
  },
  watch: {
    // 当限制素材库可上传的类型发生改变时，
    isSearchTypeChanged() {
      this.queryMaterialList();
    },

    value(val) {
      this.visible = val;
    },
    visible(visible) {
      if (visible) {
        if (this.timer) clearTimeout(this.timer);

        this.isWrapShow = true;
        this.currentMaterialType = this.category[0];

        // generate unique selected ids(Material existing and non-existing)
        this.selected = Array.from(new Set([...this.selectedIds, ...this.cached]));
      } else {
        this.clear();

        this.timer = setTimeout(() => {
          this.isWrapShow = false;
          this.currentMaterialType = '';
        }, 300);
      }
    },

    currentMaterialType(type) {
      this.pageIndex = 1;
      if (type) {
        this.polling();
      }
    },
    isTranscoding(flag) {
      if (!flag) {
        this.clear();
      }
    }
  },

  methods: {
    close() {
      this.visible = false;
      this.$emit('update:value', false);
    },
    // 两个作用，查询素材列表和查询要插入的素材列表
    queryMaterialList(ids) {
      let { currentMaterialType, category, subCategory, pageIndex, pageSize } = this;
      let materialType = currentMaterialType && currentMaterialType !== 'all'
        ? currentMaterialType
        : category.filter(c => c !== 'all').join(',')
      let materialSubType = subCategory.join(',');
      let params = ids ? {
        materialIds: ids,
        pageIndex: 1,
        pageSize: 99
      } : {
        materialType,
        materialSubType,
        pageIndex,
        pageSize
      }

      return this.$store
        .dispatch('proxyAction', {
          name: 'materialSearchV2',
          message: false,
          data: params
        })
        .then(({ data }) => {
          if (ids) {
            return data.rows;
          } else {
            this.materialList = data.rows;
            this.total = data.total;
          }
        })
        .catch(({ message }) => {
          this.$emit('on-error', {
            code: 50001,
            message: message
          });
          this.materialList = [];
          this.total = 0;
        })
    },

    // 轮询
    async polling() {
      this.clear();

      await this.queryMaterialList(); // 页签、页码切换时，立即调用
      if (this.isTranscoding) {
        this.pollingTimer = setInterval(() => this.queryMaterialList(), 3000);
      }
    },
    clear() {
      if (this.pollingTimer) {
        clearInterval(this.pollingTimer);
      }
    },

    onTypeChanged(type) {
      this.currentMaterialType = type;
    },
    onPageChanged(pageIndex) {
      this.pageIndex = pageIndex;
      this.polling();
    },

    // 更新上传列表
    handleUploadListChanged(uploadList) {
      this.uploadList = uploadList;
    },
    // 更新当前上传的文件
    handleUploadFileChanged(uploadFile) {
      this.uploadFile = uploadFile;

      // if (this.currentMaterialType !== 'all') {
      //   this.currentMaterialType = 'all';
      // }
      // TODO 匹配类型，然后根据类型做出对应的 tab 切换
    },
    handleUploadSuccess() {
      // if (this.currentMaterialType === 'all') {
      //   this.polling();
      // } else {
      //   this.currentMaterialType = 'all';
      // }
      this.pageIndex = 1;
      this.polling();
    },

    // 限定类型不匹配，被拒绝上传
    onRejected(message) {
      this.$emit('on-rejected', message);
    },

    // 重新上传
    handleReUploadByKey(key) {
      this.$refs.uploader.reUploadByKey(key);
    },
    // 从列表中移除
    handleUploadFileRemove(key) {
      this.$refs.uploader.removeUploadFileFromTheQueue(key);
    },

    onSelected(item) {
      if (this.disableSelect(item)) return;

      const id = item.materialId;
      if (this.mode) { // 多选
        const index = this.selected.indexOf(id);
        if (index !== -1) {
          this.selected.splice(index, 1);
        } else {
          this.selected.push(id);
        }
      } else { // 单选
        this.selected = [];
        this.selected.push(id);
      }
    },
    // 返回一个有序的、已选中的素材列表
    async onInsert() {
      if (this.disableInsert) return false;

      // 查询，并回传
      const ids = [...this.selected];
      const materialList = await this.queryMaterialList(ids);
      materialList.sort((a, b) => ids.indexOf(a.materialId) - ids.indexOf(b.materialId));

      if (materialList) {
        this.$emit('on-ok', materialList);
        this.close();
        this.cached = [];
      }
    },
    onCancel() {
      // cache selected ids
      this.cached = this.selected.filter(item => !this.selectedIds.includes(item));

      // 是否溢出
      this.diff = this.selectedIds.length + this.cached.length - this.limit;
      if (this.diff > 0) {
        this.cached = this.cached.slice(0, -this.diff);
      }

      this.close();
    },

    formatFileSize(size) {
      return formatFileSize(size);
    },
    formatTime(time) {
      return formatTime(time);
    }
  },

  unmounted() {
    this.clear();
  }
}
</script>

<style lang="scss" scoped>
@import "./index.scss";

.dialog-content {
  .header {
    position: relative;
    border-bottom: 1px solid #EAEAEA;

    .title {
      display: flex;
      align-items: center;
      padding: 0 20px;
      height: 60px;
      font-size: 18px;
      color: #111A38;
    }
    .close {
      height: 26px;
      width: 26px;
      position: absolute;
      right: 20px;
      top: 20px;
      display: flex;
      justify-content: center;
      align-items: center;
      cursor: pointer;

      .close-icon {
        font-size: 0;
        height: 14px;
        width: 14px;
        background: url(./assets/icon_close.png) no-repeat;
        background-size: contain;
      }
    }
  }
  .footer {
    border-top: 1px solid #EAEAEA;
    padding: 0 20px;
    display: flex;
    height: 60px;
    justify-content: space-between;
    align-items: center;
    font-size: 14px;
    color: #999FA7;

    .btns {
      display: flex;
      user-select: none;

      .btn {
        margin-left: 10px;
        height: 38px;
        width: 80px;
        display: inline-flex;
        justify-content: center;
        align-items: center;
        background-color: #E1E0E5;
        border-radius: 4px;
        cursor: pointer;

        &.insert {
          background-color: #5293F5;
          color: #FFFFFF;

          &.disabled {
            background-color: #E1E0E5;
            color: #999FA7;
            cursor: not-allowed;
          }
        }
      }
    }
  }

  .body {
    overflow: hidden;
    padding: 0 20px;
    * {
      box-sizing: border-box;
    }

    .body-inner {
      transform: translateY(-26px);
      margin-bottom: -26px;
      transition: all .3s linear;

      &.uploading-info--show {
        transform: translateY(0);
        margin-bottom: 0;
      }
    }

    .tabs {
      padding: 10px 0;
      display: flex;
      align-items: center;
      user-select: none;
      ul {
        font-size: 16px;
        flex: 1;
        display: flex;
        margin: 0 15px 0 -15px;
      }
      li {
        margin: 0 15px;
        padding: 5px 0;
        display: flex;
        position: relative;

        span {
          line-height: 35px;
          cursor: pointer;
        }
      }

      .active {
        font-weight: bold;
        color: #5293F5;

        &::after {
          content: '';
          position: absolute;
          bottom: 0;
          left: 50%;
          height: 3px;
          width: 16px;
          transform: translateX(-50%);
          background-color: #5293F5;
          border-radius: 2px;
        }
      }
    }
    .pane {
      height: 355px;
      position: relative;
    }

    .upload-info {
      margin-right: 15px;
      cursor: pointer;
      text-align: center;

      .review {
        margin-top: 5px;
        font-size: 12px;
      }
    }

    .material-list {
      display: flex;
      flex-wrap: wrap;
      margin: 0 -10px;
    }
    .material-item {
      width: 50%;
      margin: 0 0 10px 0;
      padding: 0 10px;
    }

    .material-item {
      &.disabled {
        .item-wrapper {
          cursor: not-allowed;
        }
      }
    }

    .item-wrapper {
      background-color: #F8F8F8;
      border: 1px solid #F2F2F2;
      border-radius: 4px;
      padding: 10px 20px;
      display: flex;
      align-items: center;
      position: relative;
      cursor: pointer;
      user-select: none;
    }
    .item-choice {
      margin-right: 20px;
      flex: none;
    }
    .item {
      flex: 1;
      min-width: 0;
      display: flex;
      align-items: center;

      .icon {
        flex: none;
        height: 32px;
        width: 32px;
        margin-right: 12px;
        display: flex;
        align-items: center;
        justify-content: center;
        .icon-mask {
          display: none;
        }
        img {
          width: 100%;
        }
      }
      .file {
        min-width: 0;
        .name {
          width: 220px;
          line-height: 21px;
          font-size: 14px;
          color: #111A38;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
        .info {
          margin-top: 2px;
          display: flex;
          line-height: 18px;
          font-size: 12px;
          color: #999;

          .size {
            margin-right: 6px;
            color: #5293F5;
          }
          .time-or-status {
            .transcoding {
              color: #FF7982;
            }
            .error {
              display: flex;
              .s1 {
                margin-right: 10px;
                color: #FF7982;
              }
              .s2 {
                color: #5293F5;
              }
            }
          }
        }
      }
    }

    .material-list.picture-card {
      .material-item {
        margin: 0 0 15px 0;
        width: 20%;
        &.disabled {
          .icon {
            .icon-mask {
              display: block;
              position: absolute;
              left: 0;
              top: 0;
              width: 100%;
              height: 100%;
              background-color: rgba(138, 138, 138, 0.9);
              z-index: 12;
            }
          }
        }
        &.selected {
          .icon {
            .icon-mask {
              display: block;
              position: absolute;
              left: 0;
              top: 0;
              width: 100%;
              height: 100%;
              background-color: rgba(0, 0, 0, 0.5);
            }
          }
        }
      }
      .item-wrapper {
        background-color: #FFF;
        padding: 0;
        border: none;
        overflow: hidden;
        border-radius: 2px;
      }
      .item-choice {
        margin: 0;
        position: absolute;
        right: 10px;
        top: 10px;
        z-index: 11;
      }
      .item {
        display: block;
        .icon {
          margin: 0;
          height: 134px;
          width: 134px;
          position: relative;
          img {
            object-fit: cover;
            height: 100%;
            width: 100%;
          }
        }
        .file {
          .name {
            margin-top: 6px;
            width: auto;
            text-align: center;
          }
          .info {
            display: none;
          }
        }
      }
    }

    .is-empty {
      padding-top: 40px;
      height: 150px;
      width: 160px;
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      font-size: 14px;
      color: #555;
      text-align: center;
      img {
        width: 70%;
        vertical-align: middle;
      }
      p {
        margin-top: 8px;
        padding-right: 2px;
      }
    }
  }
}
</style>